/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.quantprinciple.applet.dataanalysis;

import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.TimeZone;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTable;
import javax.swing.table.TableModel;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.DateAxis;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.labels.StandardXYToolTipGenerator;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYBarRenderer;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.data.time.Day;
import org.jfree.data.time.Hour;
import org.jfree.data.time.Minute;
import org.jfree.data.time.RegularTimePeriod;
import org.jfree.data.time.Second;
import org.jfree.data.time.TimeSeries;
import org.jfree.data.time.TimeSeriesCollection;

/**
 *
 * 
 * @author Q. Boiler
 */
public class TableToChartTabbedPane {

		private JTabbedPane tabbedPane = new JTabbedPane();
		private static final SimpleDateFormat yyyyMMddFormat = new SimpleDateFormat("yyyy-MM-dd");
		private static final SimpleDateFormat yyyyMMddHHFormat = new SimpleDateFormat("yyyy-MM-dd HH");
		private static final SimpleDateFormat yyyyMMddHHmmFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm");
		private static final SimpleDateFormat yyyyMMddHHmmssFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		private static final Map<Class, SimpleDateFormat> classFormatMap = new HashMap<Class, SimpleDateFormat>();
		

		static {
				classFormatMap.put(Day.class, yyyyMMddFormat);
				classFormatMap.put(Hour.class, yyyyMMddHHFormat);
				classFormatMap.put(Minute.class, yyyyMMddHHmmFormat);
				classFormatMap.put(Second.class, yyyyMMddHHmmssFormat);
		}
		TableModel tableModle;
		ChartComponents chartComps;

		public void setDataViewTab(TableModel tm) {
				tableModle = tm;
				JPanel panel = new JPanel(new BorderLayout());
				JTable dataTable = new JTable(tableModle);
				JScrollPane jsp = new JScrollPane();
				jsp.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
				jsp.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
				panel.add(dataTable);
				jsp.getViewport().add(panel);
				getTabbedPane().add("Data", jsp);
		}

		private class ChartComponents {

				private boolean isAutoRanging = false;
				private DateAxis dateAxis = null;
				private TimeSeries pagesServed;
				private TimeSeries averageSeries;
				private TimeSeriesCollection dataset = new TimeSeriesCollection();
				private HashMap machineMap = new HashMap();
				String appMachineKey;
				Class TimeSeriesClass;
		}

		private Class determineTimeClass(String s) {
				int len = s.length();
				Class clazz = null;
				if (len == 10) {
						try {
								yyyyMMddFormat.parse(s);
						} catch (ParseException ex) {
								// Bury it,  Thiis exception is being used as flow control.
								System.out.println("Cant Parse : " + s + " : " + yyyyMMddFormat.toPattern());
						}
						clazz = Day.class;
				} else if (len == 13) {
						try {
								yyyyMMddHHFormat.parse(s);
						} catch (ParseException ex) {
								// Bury it,  Thiis exception is being used as flow control.
								System.out.println("Cant Parse : " + s + " : " + yyyyMMddHHFormat.toPattern());
						}
						clazz = Hour.class;
				} else if (len == 16) {
						try {
								yyyyMMddHHmmFormat.parse(s);
						} catch (ParseException ex) {
								// Bury it,  Thiis exception is being used as flow control.
								System.out.println("Cant Parse : " + s + " : " + yyyyMMddHHmmFormat.toPattern());
						}
						clazz = Minute.class;

				} else if (len == 19) {
						try {
								yyyyMMddHHmmssFormat.parse(s);
						} catch (ParseException ex) {
								// Bury it,  Thiis exception is being used as flow control.
								System.out.println("Cant Parse : " + s + " : " + yyyyMMddHHmmssFormat.toPattern());
						}
						clazz = Second.class;
				}

				return clazz;
		}

		/**
		 * look at each value in a column and determine if the string can be parsed as a date.
		 * 
		 * @param tm
		 * @param column
		 * @return
		 */
		private Class setTimeSeriesClass(TableModel tm, int column) {
				Class clazz = null;
				for (int i = 0; i < tm.getRowCount(); ++i) {
						String date = (String) String.valueOf(tm.getValueAt(i, column));
						Class retClazz = determineTimeClass(date);
						if (retClazz == null) {
								return null;
						}
						if (clazz == null) {
								clazz = retClazz;
						} else {
								if (!clazz.equals(retClazz)) {
										return null;
								}
						}
				}
				return clazz;
		}

		public void setChartView() {
				chartComps = new ChartComponents();

				//  Determine if this is a daily, Hourly, Minute, or second report.
				chartComps.TimeSeriesClass = setTimeSeriesClass(tableModle, 0);


				// create two series that automatically discard data more than 30
				// seconds old...
				chartComps.pagesServed = new TimeSeries("Total Pages", chartComps.TimeSeriesClass);
				chartComps.pagesServed.setMaximumItemCount(tableModle.getRowCount() + 1);
				chartComps.averageSeries = new TimeSeries("Average", chartComps.TimeSeriesClass);
				chartComps.averageSeries.setMaximumItemCount(tableModle.getRowCount() + 1);

				TimeSeriesCollection volumeDataSet = new TimeSeriesCollection();

				volumeDataSet.addSeries(chartComps.pagesServed);
				chartComps.dataset.addSeries(chartComps.averageSeries);

				chartComps.dateAxis = new DateAxis();
				chartComps.dateAxis.setDateFormatOverride(new SimpleDateFormat("HH:mm"));
				chartComps.dateAxis.setLowerMargin(0.0);
				chartComps.dateAxis.setUpperMargin(0.0);
				chartComps.dateAxis.setTickLabelsVisible(true);

				NumberAxis rangeAxis = new NumberAxis("Time (Sec)");
				java.text.DecimalFormat format = new java.text.DecimalFormat("0.000");
				rangeAxis.setAutoRange(true);
				rangeAxis.setAutoTickUnitSelection(true);
				rangeAxis.setAutoRangeIncludesZero(true);
				rangeAxis.setNumberFormatOverride(format);
				rangeAxis.setLowerMargin(0.40);

				XYLineAndShapeRenderer renderer = new XYLineAndShapeRenderer(true,
						false);
				renderer.setToolTipGenerator(new StandardXYToolTipGenerator(
						"{0}: ({1}, {2})", new SimpleDateFormat("HH:mm"),
						new java.text.DecimalFormat("#0.00")));

				renderer.setSeriesPaint(0, Color.black);
				renderer.setSeriesStroke(0, new BasicStroke(1.5f,
						BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));

				renderer.setSeriesPaint(1, Color.magenta);
				for (int j = 1; j < 10; j++) {
						renderer.setSeriesStroke(j, new BasicStroke(1f,
								BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND, 0,
								new float[]{10.0f, 5.0f}, 0));
				}
				NumberAxis rangeAxis2 = new NumberAxis("Request Volume");
				java.text.DecimalFormat format2 = new java.text.DecimalFormat("#000");
				rangeAxis2.setNumberFormatOverride(format2);
				rangeAxis2.setUpperMargin(1.00); // to leave room for price line

				XYBarRenderer renderer2 = new XYBarRenderer(0.20);

				renderer2.setToolTipGenerator(new StandardXYToolTipGenerator(
						"{0}: ({1}, {2})", new SimpleDateFormat("HH:mm"),
						new java.text.DecimalFormat("#000")));

				renderer2.setSeriesPaint(0, new Color(200, 200, 240, 200));

				XYPlot xyplot = new XYPlot(volumeDataSet, chartComps.dateAxis,
						rangeAxis2, renderer2);
				// String plot_bgcolor = getParameter("plot_bgcolor");
				// if ( plot_bgcolor != null && plot_bgcolor.length()>0) {
				// xyplot.setBackgroundPaint(Color.decode(plot_bgcolor));
				// } else {
				xyplot.setBackgroundPaint(Color.WHITE);
				// }
				xyplot.setRangeAxisLocation(org.jfree.chart.axis.AxisLocation.BOTTOM_OR_RIGHT);

				xyplot.setRangeAxis(1, rangeAxis); // 1 is left axis,

				xyplot.setRangeAxisLocation(org.jfree.chart.axis.AxisLocation.BOTTOM_OR_RIGHT);
				xyplot.setDataset(1, chartComps.dataset);
				xyplot.mapDatasetToRangeAxis(1, 1);

				xyplot.setRenderer(1, renderer);

				xyplot.setDatasetRenderingOrder(org.jfree.chart.plot.DatasetRenderingOrder.FORWARD);

				JFreeChart chart = new JFreeChart("Test Title", JFreeChart.DEFAULT_TITLE_FONT,
						xyplot, false);

				chart.getPlot().setNoDataMessage("No data received yet...");

				ChartPanel cp = new ChartPanel(chart);

				tabbedPane.add("The Chart", cp);
		}

		public void updateChartView() {
				for (int i = 0; i < tableModle.getRowCount(); ++i) {
					SimpleDateFormat sdf = classFormatMap.get(chartComps.TimeSeriesClass);
					try {
       					Date d = null;//sdf.parse((String) String.valuetableModle.getValueAt(i, 0));

					    if(tableModle.getValueAt(i,0) instanceof Date){
						d=(Date)tableModle.getValueAt(i, 0);
					    }else{
						d=sdf.parse((String)tableModle.getValueAt(i, 0));
					    }
						Double column1 = Double.parseDouble(String.valueOf(tableModle.getValueAt(i, 1)));
						Double column2 = Double.parseDouble(String.valueOf(tableModle.getValueAt(i, 2)));
						
						RegularTimePeriod rtp = RegularTimePeriod.createInstance(chartComps.TimeSeriesClass, d, TimeZone.getDefault());

						if(rtp==null){
						    continue;
						}
						chartComps.averageSeries.addOrUpdate(rtp, column2);
						chartComps.pagesServed.addOrUpdate(rtp, column1);
						
					} catch (ParseException ex) {
						ex.printStackTrace();
					}

				}
		}

		public JTabbedPane getTabbedPane() {
				return tabbedPane;
		}

		public void setTabbedPane(JTabbedPane tabbedPane) {
				this.tabbedPane = tabbedPane;
		}
}
